//
//  ZData.h
//  Part of Z-Way.C library
//
//  Created by Alex Skalozub on 1/30/12.
//  Based on Z-Way source code written by Christian Paetz and Poltorak Serguei
//
//  Copyright (c) 2012 Z-Wave.Me
//  All rights reserved
//  info@z-wave.me
//
//  This source file is subject to the terms and conditions of the
//  Z-Wave.Me Software License Agreement which restricts the manner
//  in which it may be used.
//

#ifndef zddxml_h
#define zddxml_h

#include "ZPlatform.h"
#include "ZDataPrivate.h"
#include "ZLog.h"
#include "ZStreamPrivate.h"

#if defined(__ZWAY_SAVE_XML__)
#include <libxml/tree.h>
#include <libxml/xmlreader.h>
#include <libxml/xmlwriter.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#endif

#if defined(__ZWAY_SAVE_CBOR__)
#include "cbor/src/cbor.h"
#endif

typedef enum ZEncoderDecoderStatus_e
{
    ZEncoderDecoderStatus_Ok = 0x0,

    ZEncoderDecoderStatus_Unknown,
    ZEncoderDecoderStatus_UnknownDataHolderType,
    ZEncoderDecoderStatus_NotNext,
    ZEncoderDecoderStatus_FieldNotFind,
    ZEncoderDecoderStatus_SubNotFind,
    ZEncoderDecoderStatus_FieldInvalid,
    ZEncoderDecoderStatus_MapInvalid,
    ZEncoderDecoderStatus_ArrayInvalid,
    ZEncoderDecoderStatus_WrongOrder,
    ZEncoderDecoderStatus_WrongOrderInternal,
    ZEncoderDecoderStatus_BadAllocation,
    ZEncoderDecoderStatus_BadOpenFile,
    ZEncoderDecoderStatus_BadWriteFile,
    ZEncoderDecoderStatus_BadReadFile,
    ZEncoderDecoderStatus_BadSizeFile,
    ZEncoderDecoderStatus_InvalidArg,
    ZEncoderDecoderStatus_InvalidExtractNameDataHolder,
    ZEncoderDecoderStatus_BadOrder,

    ZEncoderDecoderStatus_CborNotFindLoop,

    ZEncoderDecoderStatus_XmlBadEnd,
    ZEncoderDecoderStatus_XmlBadEndEl,
    ZEncoderDecoderStatus_XmlBadAction,
    ZEncoderDecoderStatus_XmlBadStart,
    ZEncoderDecoderStatus_XmlBadAtrr,
    ZEncoderDecoderStatus_XmlBadPrintf,
    ZEncoderDecoderStatus_XmlBadStartEl,

    ZEncoderDecoderStatus_CborErrorUnknownLength,
    ZEncoderDecoderStatus_CborErrorAdvancePastEOF,
    ZEncoderDecoderStatus_CborErrorIO,
    ZEncoderDecoderStatus_CborErrorGarbageAtEnd,
    ZEncoderDecoderStatus_CborErrorUnexpectedEOF,
    ZEncoderDecoderStatus_CborErrorUnexpectedBreak,
    ZEncoderDecoderStatus_CborErrorUnknownType,
    ZEncoderDecoderStatus_CborErrorIllegalType,
    ZEncoderDecoderStatus_CborErrorIllegalNumber,
    ZEncoderDecoderStatus_CborErrorIllegalSimpleType,
    ZEncoderDecoderStatus_CborErrorNoMoreStringChunks,
    ZEncoderDecoderStatus_CborErrorUnknownSimpleType,
    ZEncoderDecoderStatus_CborErrorUnknownTag,
    ZEncoderDecoderStatus_CborErrorInappropriateTagForType,
    ZEncoderDecoderStatus_CborErrorDuplicateObjectKeys,
    ZEncoderDecoderStatus_CborErrorInvalidUtf8TextString,
    ZEncoderDecoderStatus_CborErrorExcludedType,
    ZEncoderDecoderStatus_CborErrorExcludedValue,
    ZEncoderDecoderStatus_CborErrorImproperValue,
    ZEncoderDecoderStatus_CborErrorOverlongEncoding,
    ZEncoderDecoderStatus_CborErrorMapKeyNotString,
    ZEncoderDecoderStatus_CborErrorMapNotSorted,
    ZEncoderDecoderStatus_CborErrorMapKeysNotUnique,
    ZEncoderDecoderStatus_CborErrorTooManyItems,
    ZEncoderDecoderStatus_CborErrorTooFewItems,
    ZEncoderDecoderStatus_CborErrorDataTooLarge,
    ZEncoderDecoderStatus_CborErrorNestingTooDeep,
    ZEncoderDecoderStatus_CborErrorUnsupportedType,
    ZEncoderDecoderStatus_CborErrorUnimplementedValidation,
    ZEncoderDecoderStatus_CborErrorJsonObjectKeyIsAggregate,
    ZEncoderDecoderStatus_CborErrorJsonObjectKeyNotString,
    ZEncoderDecoderStatus_CborErrorJsonNotImplemented,
    ZEncoderDecoderStatus_CborErrorInternalError,
} ZEncoderDecoderStatus_t;


typedef struct ZEncoderDecoderList_s
{
    struct ZEncoderDecoderList_s *next;
    struct ZEncoderDecoderList_s *prev;
    uint64_t ptr[];
} ZEncoderDecoderList_t;

typedef struct ZEncoderDecoderListContainer_s
{
    ZEncoderDecoderList_t *first;
    ZEncoderDecoderList_t *last;
} ZEncoderDecoderListContainer_t;

typedef enum ZEncoderDecoderType_e
{
    #if defined(__ZWAY_SAVE_XML__)
    ZEncoderDecoderType_Xml,
    #endif
    #if defined(__ZWAY_SAVE_CBOR__)
    ZEncoderDecoderType_Cbor,
    #endif
} ZEncoderDecoderType_t;

typedef enum ZEncoderDecoderName_e
{
    ZEncoderDecoderName_Controller = 0x0,
    ZEncoderDecoderName_Device,
    ZEncoderDecoderName_Data,
    ZEncoderDecoderName_Instance,
    ZEncoderDecoderName_CommanClass,
    ZEncoderDecoderName_DevicesData,
    // For controll
    ZEncoderDecoderName_Last,
} ZEncoderDecoderName_t;

typedef enum ZEncoderDecoderField_e
{
    ZEncoderDecoderField_Name = ZEncoderDecoderName_Last,
    ZEncoderDecoderField_InvalidateTime,
    ZEncoderDecoderField_UpdateTime,
    ZEncoderDecoderField_Id,
    // For controll
    ZEncoderDecoderField_Last,
} ZEncoderDecoderField_t;

#if defined(__ZWAY_SAVE_CBOR__)
typedef enum ZEncoderCborSimpleSpec_e
{
    ZEncoderCborSimpleSpec_Name = ZEncoderDecoderField_Last,
    ZEncoderCborSimpleSpec_Sub,
    ZEncoderCborSimpleSpec_UnionData,
    ZEncoderCborSimpleSpec_ArrayOfInteger,
    ZEncoderCborSimpleSpec_ArrayOfFloat,
    ZEncoderCborSimpleSpec_ArrayOfString,
} ZEncoderCborSimpleSpec_t;
#endif

#if defined(__ZWAY_SAVE_XML__)
typedef struct ZEncoderXml_s
{
    xmlTextWriterPtr writer;
    union
    {
        xmlChar xml_buffer[256];
        char char_buffer[256];
    };
    
} ZEncoderXml_t;
#endif

#if defined(__ZWAY_SAVE_CBOR__)
typedef struct ZEncoderContainerInfoCbor_s
{
    CborEncoder enc;
} ZEncoderContainerInfoCbor_t;

typedef union ZEncoderContainerInfo_u
{
    #if defined(__ZWAY_SAVE_CBOR__)
    ZEncoderContainerInfoCbor_t cbor;
    #endif
} ZEncoderContainerInfo_t;
#endif

typedef struct ZEncoder_s
{
    const _ZStreamWriter_t *stream;
    void *ctx_stream;
    union
    {
        #if defined(__ZWAY_SAVE_XML__)
        ZEncoderXml_t xml;
        #endif
    };
    ZEncoderDecoderListContainer_t container;
    ZWCSTR file_patch;
    ZWLog log;
    ZEncoderDecoderType_t type;
} ZEncoder_t;

#if defined(__ZWAY_SAVE_XML__)
typedef struct ZDecoderContainerInfoXml_s
{
    xmlNodePtr child;
    ZEncoderDecoderName_t name;
} ZDecoderContainerInfoXml_t;
#endif

#if defined(__ZWAY_SAVE_CBOR__)

typedef struct ZDecoderContainerInfoCborMap_s
{
    CborValue it;
    CborValue it_backup;
    ZEncoderDecoderName_t name;
    ZWBOOL valid;
} ZDecoderContainerInfoCborMap_t;

typedef struct ZDecoderContainerInfoCbor_s
{
    CborValue array;
    ZDecoderContainerInfoCborMap_t map;
} ZDecoderContainerInfoCbor_t;
#endif

typedef union ZDecoderContainerInfo_u
{
    #if defined(__ZWAY_SAVE_XML__)
    ZDecoderContainerInfoXml_t xml;
    #endif
    #if defined(__ZWAY_SAVE_CBOR__)
    ZDecoderContainerInfoCbor_t cbor;
    #endif
} ZDecoderContainerInfo_t;

#if defined(__ZWAY_SAVE_XML__)
typedef struct ZDecoderXml_s
{
    xmlDocPtr doc;
} ZDecoderXml_t;
#endif

#if defined(__ZWAY_SAVE_CBOR__)
typedef struct ZDecoderCbor_s
{
    CborParser parser;
} ZDecoderCbor_t;
#endif

typedef struct ZDecoder_s
{
    const _ZStreamReader_t *stream;
    void *ctx_stream;
    ZDataRootObject root;
    union
    {
        #if defined(__ZWAY_SAVE_XML__)
        ZDecoderXml_t xml;
        #endif
        #if defined(__ZWAY_SAVE_CBOR__)
        ZDecoderCbor_t cbor;
        #endif
    };
    ZEncoderDecoderListContainer_t container;
    ZEncoderDecoderType_t type;
} ZDecoder_t;

// for support z-enocean, z-matter and z-bee
#if defined(__ZWAY_SAVE_XML__)
ZWEXPORT_PRIVATE ZWError _zddxml_save_data_to_xml(const ZWLog zlog, const ZDataHolder data, xmlTextWriterPtr writer);
ZWEXPORT_PRIVATE ZDataHolder _zddxml_load_data_from_xml(ZWLog zlog, ZDataHolder realRoot, ZDataHolder newRoot, xmlNodePtr node);
#endif

#endif//zddxml_h
